<?php

namespace helper;

use Firebase\JWT\JWT;

class JwtHelper
{
    /**
     * @var string JWT 签名SECRET
     */
    protected $secret = '';

    /**
     * @var int JWT 过期时间
     */
    protected $ttl = 60;

    /**
     * @var string
     */
    protected $alg = 'HS256';

    /**
     * 设置额外的参数
     * @var null
     */
    protected $headers = [];

    //存储的数据
    protected $tokenData = null;

    protected static $instance = null;

    public function __construct()
    {
        $secret       = config('jwt.secret');
        $ttl          = config('jwt.ttl');
        $alg          = config('jwt.alg');
        $this->secret = $secret;
        $this->ttl    = $ttl;
        if (!empty($alg)) $this->alg = $alg;
    }

    /**
     * 单例模式运行
     * @return JwtHelper|null
     */
    public static function make()
    {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * 获取TOKEN
     * @param array $data
     * @return string
     */
    public function token(array $data = array())
    {
        $hmc_data               = [];
        $hmc_data['timestamp']  = time();
        $hmc_data['verifyTime'] = time() + $this->ttl;
        $hmc_data['alg']        = $this->alg;
        $hmc_data['data']       = $data;
        return JWT::encode($hmc_data, $this->secret, $this->alg, NULL, $this->headers);
    }

    /**
     * 解密TOKEN
     * @param $token
     * @return object
     * @throws \Exception
     */
    private function jwtDecodeData($token)
    {
        if (empty($token)) {
            exception('token is empty!');
        }
        return JWT::decode($token, $this->secret, ['HS256', 'HS384', 'HS512', 'RS256', 'RS384', 'RS512']);
    }

    /**
     * 校验TOKEN
     * @param $token
     * @return bool
     * @throws \Exception
     */
    public function verfiyToken($token)
    {
        if (empty($token)) {
            exception('token is empty!');
        }
        $decodeData = $this->jwtDecodeData($token);
        if (!isset($decodeData->timestamp) || !isset($decodeData->verifyTime)) {
            exception('Token is Invaild!');
        }
        if (time() > ($decodeData->verifyTime + config('jwt.allow_ttl'))) exception('The token is Expired!');
        $this->tokenData = $decodeData;
        return true;
    }

    /**
     * 刷新TOKEN
     * @param $token
     * @return string
     * @throws \Exception
     */
    public function refreshToken($token)
    {
        $decodeData = $this->JwtDecodeData($token);
        if (time() - $decodeData->verifyTime > config('jwt.allow_ttl')) {
            exception('已经超过最大刷新时间');
        }
        return $this->token($this->objectToArray($decodeData->data));
    }

    /**
     * 对象转数组
     * @param $data
     * @return mixed
     */
    public function objectToArray($data)
    {
        return json_decode(json_encode($data), true);
    }

    /**
     * 获取加密的内容
     * @return null
     */
    public function decodeData()
    {
        if (isset($this->tokenData->data)) {
            return $this->objectToArray($this->tokenData->data);
        }
        return null;
    }

    /**
     * 获取所有的加密数据
     * @return null
     */
    public function all()
    {
        if (empty($this->tokenData)) return null;
        return $this->objectToArray($this->tokenData);
    }

}